﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml;

using Microsoft.WindowsAPICodePack.DirectX.Direct2D1;
using Microsoft.WindowsAPICodePack.DirectX.DirectWrite;
using Microsoft.WindowsAPICodePack.DirectX.Graphics;
using Microsoft.WindowsAPICodePack.DirectX.WindowsImagingComponent;
using PresentOptions = Microsoft.WindowsAPICodePack.DirectX.Direct2D1.PresentOptions;

using System.Diagnostics;

namespace Framework
{
    public class SilverlightHost
    {
        public string RuntimeVersion;
        public object OutOfBrowserSettings;
        public string GpuInformation;
        
        public static bool ClipboardContainsText;
        public static string ClipboardGetText;
        public static string ClipboardSetText;
    }
    
    public class Application
    {
        public SilverlightHost Host;
        public static Application Current;
        public Window MainWindow;
        public UIElement RootVisual;
        public Dictionary<string,object> Resources = new Dictionary<string,object>();
                
        public static Dictionary<string,Template> DefaultTemplate = new Dictionary<string, Template>();

        public Application()
        {
            Current = this;
            Host = new SilverlightHost();
        }

        public static void Run(Window window)
        {
            System.Windows.Forms.Application.Run(window);
        }

        public void LoadComponent(Application component,string path)
        {
        }

        public void LoadAssembly(Application component,string path)
        {
        }

        public event EventHandler Exit;
        public event EventHandler Startup;
        public event EventHandler UnhandledException;

    }

    public sealed class Window : System.Windows.Forms.Form
    {
        //public double Height { get; set; }
        //public double Width { get; set; }
        //public double Left { get; set; }
        //public double Top { get; set; }
        //public bool TopMost { get; set; }
        //public WindowState WindowState { get; set; }
        
        [Map("FocusManager.GetFocusedElement")]
        public UIElement GetFocusedElement;

        public bool IsActive { get; set; }
        public event EventHandler<ClosingEventArgs> Closing;

        public Stopwatch watch;
        public Context Context { get; set; }
        
        public List<UIElement> elements = new List<UIElement>();
        public static Window current;

        public D2DFactory d2dFactory;
        public ImagingFactory imagingFactory;
        public DWriteFactory writeFactory;
        public HwndRenderTarget renderTarget;
        public readonly ColorF bgColor = new ColorF(Color.Transparent.ToArgb());
        public Microsoft.WindowsAPICodePack.DirectX.Direct2D1.Brush Brush;
        public TextFormat textFormat;
        //public StrokeStyle TextBoxStroke;
        private RenderTargetProperties renderProps;
        


        public Window()
        {
            watch = new Stopwatch();

            current = this;
            Height = 480;
            Width = 640;

            this.Load += delegate
            {
                renderProps = new RenderTargetProperties
                {
                    PixelFormat = new PixelFormat(Format.B8G8R8A8UNorm, AlphaMode.Ignore),
                    Usage = RenderTargetUsages.None,
                    RenderTargetType = RenderTargetType.Software
                };

                d2dFactory = D2DFactory.CreateFactory(D2DFactoryType.Multithreaded);
                writeFactory = DWriteFactory.CreateFactory();
                imagingFactory = ImagingFactory.Create();

                textFormat = writeFactory.CreateTextFormat("Gabriola", 32);

                //TextBoxStroke = d2dFactory.CreateStrokeStyle(
                //    new StrokeStyleProperties(
                //        CapStyle.Flat, CapStyle.Flat, CapStyle.Round,
                //        LineJoin.Miter, 5.0f, DashStyle.Dash, 3f),
                //    null);
            };

            this.Load += delegate
            {
                elements.Add(new Line() { X1 = 0.0, X2 = 200.0, Y1 = 5.0, Y2 = 5.0, StrokeThickness = 5.0 });
                elements.Add(new Line() { X1 = 0.0, X2 = 200.0, Y1 = 25.0, Y2 = 25.0, StrokeThickness = 10.0 });
                elements.Add(new Line() { X1 = 0.0, X2 = 200.0, Y1 = 45.0, Y2 = 45.0, StrokeThickness = 15.0 });
                //elements.Add(new Rectangle() { X = 100.0, Y = 110.0, Width = 205, Height = 50, StrokeThickness = 2.0, Stroke = new SolidColorBrush(Color.Black), Fill = new SolidColorBrush(Color.Transparent), RadiusX = 10.0, RadiusY = 10.0 });
                //elements.Add(new Ellipse() { X = 100.0, Y = 110.0, RadiusX = 400, RadiusY = 400 });
            };

            this.SizeChanged += delegate
            {
                if (renderTarget != null)
                {
                    SizeU newsize = new SizeU((uint)this.ClientSize.Width, (uint)this.ClientSize.Height);
                    renderTarget.Resize(newsize);
                }
            };

            /*
            this.MouseClick += delegate(object sender, MouseEventArgs e)
            {
                Console.WriteLine("Clicked");
            };
             */
        }

        void CreateDeviceResources()
        {
            if (renderTarget == null)
            {
                SizeU size = new SizeU((uint)this.ClientSize.Width, (uint)this.ClientSize.Height);
                HwndRenderTargetProperties hwndProps = new HwndRenderTargetProperties(this.Handle, size, PresentOptions.RetainContents);
                renderTarget = d2dFactory.CreateHwndRenderTarget(renderProps, hwndProps);
                Brush = renderTarget.CreateSolidColorBrush(new ColorF(Color.Black.ToArgb()));
            }
        }

        protected override void OnPaint(PaintEventArgs args)
        {
            watch.Start();

            CreateDeviceResources();

            if (renderTarget.IsOccluded)
                return;

            renderTarget.BeginDraw();

            renderTarget.Clear(bgColor);

            foreach (var i in elements)
            {
                i.Draw(this, renderTarget);
            }

            string text = "Inline Object Sample";



            renderTarget.DrawText(text, textFormat, new RectF(100f, 200f, 400f, 100f),Brush);

            renderTarget.EndDraw();

            watch.Stop();

            Console.WriteLine(watch.ElapsedTicks);

            watch.Reset();
        }
        
        //public bool Activate() 
        //{             
        //}


        //public virtual void Close() 
        //{             
        //}

        //public void DragMove()
        //{
        //}

        //public void DragResize(WindowResizeEdge resizeEdge)
        //{
        //}

    }

    public sealed class NotificationWindow : Base
    {
        public UIElement Content;
        public double Height;
        public double Width;
        public Visibility Visibility;

        public void Close()
        {
        }

        public void Show(int durationInMilliseconds)
        {
        }

        public event EventHandler Closed;
    }

    public sealed class MessageBox
    {
        public static MessageBoxResult Show(string messageBoxText,string caption,MessageBoxButton button)
        {
            throw new NotImplementedException();
        }
    }

    public enum MessageBoxButton
    {
        OK, OKCancel
    }

    public enum MessageBoxResult
    {
        None,OK,Cancel,Yes,No
    }

    public class ClosingEventArgs : CancelEventArgs
    {
        public bool IsCancelable;
    }

    public enum WindowResizeEdge
    {
        Left,
        Right,
        Top,
        TopLeft,
        TopRight,
        Bottom,
        BottomLeft,
        BottomRigh
    }

    public enum WindowState
    {
        Normal,
        Minimized,
        Maximized
    }
}
